﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.UI.WebControls;
using Intellego.Web.ValidationEngine;
using MIAP.Entidades;
using MIAP.Entidades.Enums;
using MIAP.Negocio;
using MIAP.Negocio.Utiles;
using MIAPWEB.Common;

namespace MIAPWEB.Forms
{
    /// <summary>
    /// Clase de la vista AltaArchivo.
    /// </summary>
    public partial class AltaArchivo : PageBase
    {
        #region Variables
        /// <summary>
        /// Clase de negocio para archivos
        /// </summary>
        private readonly AltaArchivosNegocio altaArchivoBussines;

        /// <summary>
        /// Clase de negocio para las operaciones comunes del sistema.
        /// </summary>
        private ComunesNegocio comunesNegocio;

        /// <summary>
        /// variable para consultarlos elementos acutales
        /// </summary>
        private ConfiguracionNegocio ConsultaConfiguracion;

        #endregion

        #region Constructores

        public AltaArchivo()
        {
            this.altaArchivoBussines = new AltaArchivosNegocio();
            this.comunesNegocio = new ComunesNegocio();
            this.ConsultaConfiguracion = new ConfiguracionNegocio();
        }

        #endregion

        #region Propiedades

        /// <summary>
        /// Id del archivo 
        /// </summary>
        private int? IdArchivo
        {
            get
            {
                if (this.ViewState[AppQueryStrings.IdArchivo] == null)
                {
                    this.ViewState[AppQueryStrings.IdArchivo] = this.Request.QueryString[AppQueryStrings.IdArchivo];
                }

                return Convert.ToInt32(this.ViewState[AppQueryStrings.IdArchivo]);
            }

            set
            {
                this.ViewState[AppQueryStrings.IdArchivo] = value;
            }
        }

        /// <summary>
        /// Lista de usuarios
        /// </summary>
        private IList<UsuarioInfo> ListaUsuarios
        {
            get
            {
                if (this.ViewState["ListaUsuarios"] == null)
                {
                    this.ViewState["ListaUsuarios"] = new List<UsuarioInfo>();
                }
                return this.ViewState["ListaUsuarios"] as List<UsuarioInfo>;
            }
            set
            {
                this.ViewState["ListaUsuarios"] = value;
            }
        }
        private bool aplicaTodasReglas
        {
            get
            {
                if (this.ViewState["aplicaTodasReglas"] == null)
                {
                    this.ViewState["aplicaTodasReglas"] = false;
                }
                return (bool)this.ViewState["aplicaTodasReglas"];
            }
            set
            {
                this.ViewState["aplicaTodasReglas"] = value;
            }
        }

        #endregion

        #region Eventos

        /// <summary>
        /// Evento que se ejecuta al cargar la página.
        /// </summary>
        /// <param name="sender">Objeto que invoca el evento.</param>
        /// <param name="e">Argumentos del evento.</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!this.IsPostBack)
            {
                aplicaTodasReglas = true;
                this.grdUsuarios.PageSize = Convert.ToInt32(new ConfiguracionNegocio().GetNumeroPaginasGrid().Descripcion);
                if (Request.UrlReferrer != null) this.PreviousPage = Request.UrlReferrer.ToString();
                this.LoadinitialCatalogs();
                this.lblTitulo.Text = this.GetGlobalResourceObject("Strings", "lblTituloAltaArchivos").ToString();
                if (this.IdArchivo != null && this.IdArchivo > 0)
                {
                    this.LoadArchivo((int)this.IdArchivo);
                    aplicaTodasReglas = false;
                    this.lblTitulo.Text = this.GetGlobalResourceObject("Strings", "lblTituloEdicionArchivos").ToString();
                }
            }

            this.InitValidation(aplicaTodasReglas);
        }

        /// <summary>
        /// Carga la informacion del archivo en los combos
        /// </summary>
        /// <param name="idArchivo"></param>
        private void LoadArchivo(int idArchivo)
        {
            var archivo = this.altaArchivoBussines.GetArchivoById(idArchivo);

            this.IdArchivo = archivo.IdentificadorArchivo;
            this.txtNombre.Text = archivo.NombreArchivo;
            this.txtDescripción.Text = archivo.Descripcion;
            this.TxtNombrePaquete.Text = archivo.ProcedimientoCarga;
            this.ddlEstatus.SelectedValue = Convert.ToInt32(archivo.EstaActivo == Enum.GetName(typeof(Estatus), Estatus.Activo)).ToString();
            this.ddlObligatorio.SelectedValue = Convert.ToInt32(archivo.EsObligatorio == Enum.GetName(typeof(SiNo), SiNo.Si)).ToString();
            this.ddlVersion.SelectedValue = Convert.ToInt32(archivo.EsVersion == Enum.GetName(typeof(SiNo), SiNo.Si)).ToString();

            this.ddlProyecto.SelectedValue = archivo.Proyecto.IDProyecto.ToString();
            this.ddlFormatoArchivo.SelectedValue = archivo.FormatoArchivo.IdentificadorFormatoArchivo.ToString();
            var boletos = this.ConsultaConfiguracion.GetVariablesPaquete(archivo.Proyecto.NombreProyecto,
                                                                         archivo.NombreArchivo);
            this.wucVariablesDtsx.AddControls(boletos);
            //recargamos la lista de usuarios con aquellos que ya se habian guardado antes.
            this.ListaUsuarios = this.altaArchivoBussines.GetTodosUsuariosConCarga(idArchivo);
            this.grdUsuarios.DataSource = ListaUsuarios;
            this.grdUsuarios.DataBind();
        }


        /// <summary>
        /// Llena los drop downs con la informacion inicial
        /// </summary>
        private void LoadinitialCatalogs()
        {
            var listaSiNo = this.comunesNegocio.GetSiNo();
            this.ddlProyecto.DataSource = AppSessionManager.Instance.GetProyectosByPagina(AppUrls.AltaArchivos);
            this.ddlProyecto.DataBind();
            this.ddlFormatoArchivo.DataSource = this.altaArchivoBussines.GetFormatosArchivo();
            this.ddlFormatoArchivo.DataBind();
            this.ddlEstatus.DataSource = this.comunesNegocio.GetEstatus();
            this.ddlEstatus.DataBind();
            this.ddlObligatorio.DataSource = listaSiNo;
            this.ddlObligatorio.DataBind();
            this.ddlVersion.DataSource = listaSiNo;
            this.ddlVersion.DataBind();

            this.ListaUsuarios = this.altaArchivoBussines.GetUsuarios();
            this.grdUsuarios.DataSource = this.ListaUsuarios;
            this.grdUsuarios.DataBind();
        }

        protected void btnGuardar_Click(object sender, EventArgs e)
        {
            if (this.IdArchivo == default(int) || this.IdArchivo == null)
            {
                string nombreArchivo = this.txtNombre.Text.Trim().ToLower();

                nombreArchivo = Regex.Replace(nombreArchivo, @"\s+", " ");

                if (this.VerifyExistNombreArchivoInProyecto(int.Parse(this.ddlProyecto.SelectedValue), nombreArchivo))
                {
                    this.ShowMessage(this.GetGlobalResourceObject("Strings", "AltaArchivo_ArchivoExistente").ToString());
                }
                else
                {
                    this.Save();
                }
            }
            else
            {
                this.Save();
            }
        }

        /// <summary>
        /// Guarda la informacion de un archivo
        /// </summary>
        private void Save()
        {
            var xml = string.Empty;
            if (fuArchivoXml.HasFile)
            {
                using (var reader = new StreamReader(fuArchivoXml.FileContent))
                {
                    xml = reader.ReadToEnd();
                }
                xml = Regex.Replace(xml, "&(?!(amp)|(lt)|(apos)|(gt)|(quot);)", "&amp;");
                if (String.IsNullOrEmpty(xml.Trim())||xml.Trim() ==this.GetGlobalResourceObject("Strings", "EncabezadoXML").ToString().Trim())
                {
                    this.ShowMessage(this.GetGlobalResourceObject("Strings", "ArchivoVacio").ToString());
                    return;                    
                }

                var validador = new ValidadorXml(Request.PhysicalApplicationPath + AppUrls.XsdMIAP);
                if (!validador.CompruebaXmLvsXsd(xml))
                {
                    var mensaje = new StringBuilder();
                    mensaje.Append(validador.Advertencias);
                    mensaje.AppendLine(validador.Errores);
                    this.wucListaErrores.ListaErrores = mensaje.ToString();
                    this.ListaErroresPanelModalPopupExtender.Show();
                    return;
                }
            }
            var loArchivo = this.IdArchivo.HasValue && this.IdArchivo.Value > 0
                              ? this.altaArchivoBussines.GetArchivoById(this.IdArchivo.Value)
                              : new ArchivoInfo();
            var nombreAntes = loArchivo.NombreArchivo;
            loArchivo.NombreArchivo = this.txtNombre.Text;
            loArchivo.Descripcion = this.txtDescripción.Text;

            loArchivo.EstaActivo = ddlEstatus.SelectedItem.Text;
            loArchivo.EsObligatorio = this.ddlObligatorio.SelectedItem.Text;
            loArchivo.EsVersion = this.ddlVersion.SelectedItem.Text;
            loArchivo.Proyecto = new ProyectoInfo { IDProyecto = Convert.ToInt32(this.ddlProyecto.SelectedValue) };
            loArchivo.FormatoArchivo = new FormatoArchivoInfo { IdentificadorFormatoArchivo = Convert.ToInt32(this.ddlFormatoArchivo.SelectedValue) };
            loArchivo.PeriodoInformacion = null;
            loArchivo.PeriodoCarga = null;

            if (txtNombre.Text != string.Empty)
            {
                loArchivo.ProcedimientoCarga = this.TxtNombrePaquete.Text;
            }

            if (!String.IsNullOrEmpty(xml))
            {
                loArchivo.EsquemaArchivoXML = xml;
            }
            this.UpdateSelectedUsers();
            var usuarios = this.ListaUsuarios.Select(usuarioInfo => new UsuarioInfo(usuarioInfo)).ToList();

            var valoresParametros = this.wucVariablesDtsx.GetValores();
            var confignegocio = new ConfiguracionNegocio();
            var mensajeGuardado = this.GetGlobalResourceObject("strings", "GuardadoExitoso").ToString();
            if (this.IdArchivo == null || this.IdArchivo == 0)
            {
                this.altaArchivoBussines.AddNewArchivo(loArchivo, AppSessionManager.Instance.Usuario, usuarios);
                confignegocio.SetVariablesPaquete(this.ddlProyecto.SelectedItem.Text, this.txtNombre.Text
                    , AppSessionManager.Instance.Usuario, valoresParametros);
                this.ShowMessage(mensajeGuardado);
            }
            else
            {
                this.altaArchivoBussines.EditArchivo(loArchivo, AppSessionManager.Instance.Usuario, usuarios);
                confignegocio.EditVariablesPaquete(string.Empty, this.ddlProyecto.SelectedItem.Text, nombreAntes, this.txtNombre.Text
             , AppSessionManager.Instance.Usuario, valoresParametros);
                this.ShowMessage(mensajeGuardado, this.PreviousPage);
            }

            this.Clean();
        }


        /// <summary>
        /// limpia los controles actuales
        /// </summary>
        private void Clean()
        {
            this.wucVariablesDtsx.Clean();
            this.IdArchivo = null;
            this.txtNombre.Text = string.Empty;
            this.txtDescripción.Text = string.Empty;
            this.txtNombre.Text = string.Empty;
            this.TxtNombrePaquete.Text = string.Empty;
            this.ddlEstatus.SelectedIndex = 0;
            this.ddlObligatorio.SelectedIndex = 0;
            this.ddlVersion.SelectedIndex = 0;
            this.fuArchivoXml.Dispose();
            this.ddlProyecto.SelectedIndex = 0;
            this.ddlFormatoArchivo.SelectedIndex = 0;
            foreach (var listaUsuario in this.ListaUsuarios)
            {
                listaUsuario.IsChecked = false;
            }
            grdUsuarios.DataSource = this.ListaUsuarios;
            grdUsuarios.DataBind();
        }

        protected void btnSalir_Click(object sender, EventArgs e)
        {
            Response.Redirect(this.PreviousPage);
        }
        #endregion

        #region Métodos

        /// <summary>
        /// Agregar las validaciones para los campos requeridos.
        /// </summary>
        private void InitValidation(bool aplicaTodas)
        {
            var ddlpermitido = this.GetGlobalResourceObject("strings", "ErrorDropDownRequerido").ToString();
            var requerido = this.GetGlobalResourceObject("strings", "ErrorRequerido").ToString();
            var ruleNombre = new ValidationRule(this.txtNombre);
            var ruleIdProyecto = new ValidationRule(this.ddlProyecto);
            var ruleIdFormatoArchivo = new ValidationRule(this.ddlFormatoArchivo);
            var ruleObligatorio = new ValidationRule(this.ddlObligatorio);
            var ruleVersion = new ValidationRule(this.ddlVersion);
            var ruleActivo = new ValidationRule(this.ddlEstatus);

            ruleNombre.NotEmpty(requerido);
            ruleIdProyecto.NotEmpty(ddlpermitido);
            ruleIdFormatoArchivo.NotEmpty(ddlpermitido);
            ruleObligatorio.NotEmpty(ddlpermitido);
            ruleVersion.NotEmpty(ddlpermitido);
            ruleActivo.NotEmpty(ddlpermitido);

            this.ValidationEngine.Add(ruleNombre);
            this.ValidationEngine.Add(ruleIdProyecto);
            this.ValidationEngine.Add(ruleIdFormatoArchivo);
            this.ValidationEngine.Add(ruleObligatorio);
            this.ValidationEngine.Add(ruleActivo);

            //Agrega la opción para respetar la longitud máxima en las cajas de texto multilínea
            this.ValidationEngine.FixTextBoxMultiLine = true;
            //Agrega la opción para respetar la longitud máxima en las cajas de texto multilínea
            this.ValidationEngine.FixTextBoxMultiLine = true;

            if (!aplicaTodas) return;

            var ruleXML = new ValidationRule(this.fuArchivoXml);
            var rulePaquete = new ValidationRule(this.TxtNombrePaquete);

            ruleXML.NotEmpty(requerido);
            ruleXML.Matches("(.xml)$", this.GetGlobalResourceObject("strings", "ErrorXMLPermitido").ToString());

            rulePaquete.NotEmpty(requerido);
            // rulePaquete.Matches("(.dtsx)$", this.GetGlobalResourceObject("strings", "ErrorDtsxPermitido").ToString());

            this.ValidationEngine.Add(ruleXML);
            this.ValidationEngine.Add(rulePaquete);
        }

        #endregion

        protected void grdUsuarios_PageIndexChanging(object sender, GridViewPageEventArgs e)
        {
            UpdateSelectedUsers();
            grdUsuarios.PageIndex = e.NewPageIndex;
            grdUsuarios.DataSource = this.ListaUsuarios;
            grdUsuarios.DataBind();
        }

        /// <summary>
        /// Actualizalos usuarios que han sido seleccionados en la pagina actual del grid
        /// </summary>
        private void UpdateSelectedUsers()
        {
            foreach (GridViewRow row in this.grdUsuarios.Rows)
            {
                var chkSeleccionar = (CheckBox)row.FindControl("chkSeleccionar");
                var dataKey = grdUsuarios.DataKeys[row.RowIndex];
                var id = (int)dataKey.Value;
                this.ListaUsuarios.Single(elemento => elemento.IdUsuario == id).IsChecked = chkSeleccionar.Checked;
            }
        }

        /// <summary>
        /// Verifica la existencia de un archivo en un determinado proyecto.
        /// </summary>
        /// <param name="idProyecto">Es el id del proyecto con el que esta ligado el archivo.</param>
        /// <param name="nombreArchivo">Es el nombre del archivo.</param>
        /// <returns>Indicador de si el archivo existe o no y esta ligado al id del proyecto.</returns>
        public bool VerifyExistNombreArchivoInProyecto(int idProyecto, string nombreArchivo)
        {
            return this.altaArchivoBussines.VerifyExistNombreArchivoInProyecto(idProyecto, nombreArchivo);
        }

        protected void CargarVariables_btnClick(object sender, EventArgs e)
        {
        }

        protected void lnkVariables_OnClick(object sender, EventArgs e)
        {
            VariablesModalPopupExtender.Show();
        }
    }
}